﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace StarHelper
{
    public class HttpHelper
    {
        public static HttpHelper httpHelper = new HttpHelper(Encoding.UTF8);
        /// <summary>
        /// 访问头
        /// </summary>
        const string USERAGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36";

        Encoding pageEncoding = Encoding.UTF8;

        CookieContainer cookie;
        WebProxy proxy;
        Dictionary<string, string> headers = null;

        public HttpHelper(Encoding encoding)
        {
            pageEncoding = encoding;
            cookie = new CookieContainer();
            proxy = new WebProxy();
        }

        public void SetHeader(Dictionary<string, string> Headers)
        {
            headers = Headers;
        }

        public string UrlGet(string Url, ref int HttpCode, int TryCount)
        {
            return HttpGet(Url, ref HttpCode, TryCount, "");
        }

        public string UrlGet(string Url, ref int HttpCode)
        {
            return HttpGet(Url, ref HttpCode, 3, "");
        }

        public string UrlGet(string Url, ref int HttpCode, string Referer)
        {
            return HttpGet(Url, ref HttpCode, 3, Referer);
        }

        public string UrlGet(string Url, ref int HttpCode, int TryCount, string Referer)
        {
            return HttpGet(Url, ref HttpCode, TryCount, Referer);
        }

        public void UrlDownText(string Url, string FilePath)
        {
            int code = 0;
            string ct = HttpGet(Url, ref code, 0, "");
            if (code == 200)
            {
                if (!string.IsNullOrEmpty(ct))
                {
                    File.WriteAllText(FilePath, ct);
                }
            }
        }

        /// <summary>
        /// 清除Cookies
        /// </summary>
        public void ClearCookies()
        {
            if (cookie != null)
            {
                cookie = new CookieContainer();
            }
        }


        /// <summary>
        /// 设置代理服务器
        /// </summary>
        /// <param name="Ip">如果IP为空，则表示取消代理</param>
        /// <param name="Port"></param>
        public bool SetProxy(string IpPort)
        {
            if (!string.IsNullOrEmpty(IpPort))
            {
                proxy.Address = new Uri(string.Format("http://{0}", IpPort));

                //测试地址是否可用
                int code = 0;
                string html = HttpGet("http://www.baidu.com/", ref code, 0, "");
                if (code == 200)
                {
                    return true;
                }
                else
                {
                    proxy.Address = null;
                    return false;
                }

            }
            else
            {
                proxy.Address = null;
                return true;
            }
        }

        /// <summary>
        /// 获取当前代理地址和端口
        /// </summary>
        /// <returns></returns>
        public string GetProxyIpPort()
        {
            if (proxy != null && proxy.Address != null)
            {
                return string.Format("{0}:{1}", proxy.Address.Host, proxy.Address.Port);
            }

            return "";
        }



        public void UrlDownFile(string Url, string FilePath, string Referer = "")
        {
            try
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
                req.Method = "GET";
                req.UserAgent = USERAGENT;
                req.Timeout = 2 * 60 * 1000; //2分钟
                req.KeepAlive = true;
                req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
                if (!string.IsNullOrEmpty(Referer))
                {
                    req.Referer = Referer;
                }
                SetRequestHeader(req);

                req.CookieContainer = cookie;
                if (proxy.Address != null)
                {
                    req.Proxy = proxy;
                }

                int HttpCode = 0;

                HttpWebResponse res = (HttpWebResponse)req.GetResponse();
                if (res != null)
                {
                    HttpCode = (int)res.StatusCode;



                    Stream s = res.GetResponseStream();
                    using (FileStream fs = File.Create(FilePath))
                    {
                        byte[] btfile = new byte[1024];
                        int n = 1;
                        while (n > 0)
                        {
                            n = s.Read(btfile, 0, 1024);
                            fs.Write(btfile, 0, n);
                        }

                    }
                    s.Close();
                }
                res.Close();
            }
            catch
            {
            }
        }

        protected string HttpGet(string Url, ref int HttpCode, int TryCount, string Referer)
        {
            string ret = string.Empty;
            try
            {
                if (Url.Contains("https://"))
                {
                    ServicePointManager.Expect100Continue = true;
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;   //协议按需选择，不行就都试一遍
                    ServicePointManager.ServerCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => { return true; };
                }
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
                req.Method = "GET";
                req.UserAgent = USERAGENT;
                req.Timeout = 60 * 1000; //1分钟
                req.KeepAlive = true;
                req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
                SetRequestHeader(req);


                if (!string.IsNullOrEmpty(Referer))
                {
                    req.Referer = Referer;
                }

                req.CookieContainer = cookie;
                if (proxy.Address != null)
                {
                    req.Proxy = proxy;
                }

                HttpWebResponse res = (HttpWebResponse)req.GetResponse();
                if (res != null)
                {
                    HttpCode = (int)res.StatusCode;
                    Stream s = res.GetResponseStream();
                    StreamReader sr = new StreamReader(s, pageEncoding);
                    ret = sr.ReadToEnd();
                    sr.Close();
                    s.Close();
                }
                res.Close();
            }
            catch (WebException ex)
            {
                if (TryCount == 0)
                {
                    HttpCode = (int)ex.Status;
                    ret = ex.Message;
                }
                else
                {
                    if (TryCount == 1)
                    {
                        System.Threading.Thread.Sleep(60 * 1000); //1分钟
                    }
                    else
                    {
                        System.Threading.Thread.Sleep(20000); //20秒
                    }
                    TryCount--;
                    ret = HttpGet(Url, ref HttpCode, TryCount, Referer);
                }
            }


            return ret;
        }

        public string UrlPost(string Url, string Data, ref int HttpCode)
        {
            string ret = string.Empty;

            try
            {
                if (Url.Contains("https://"))
                {
                    ServicePointManager.Expect100Continue = true;
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;   //协议按需选择，不行就都试一遍
                    ServicePointManager.ServerCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => { return true; };
                }
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
                req.Method = "POST";
                req.UserAgent = USERAGENT;
                req.Timeout = 2 * 60 * 1000; //2分钟

                SetRequestHeader(req);

                byte[] btData = Encoding.UTF8.GetBytes(Data);
                req.ContentLength = btData.Length;
                req.ContentType = "application/x-www-form-urlencoded";

                req.CookieContainer = cookie;
                if (proxy.Address != null)
                {
                    req.Proxy = proxy;
                }


                Stream sreq = req.GetRequestStream();
                sreq.Write(btData, 0, btData.Length);
                sreq.Close();

                HttpWebResponse res = (HttpWebResponse)req.GetResponse();
                if (res != null)
                {
                    HttpCode = (int)res.StatusCode;
                    Stream s = res.GetResponseStream();
                    StreamReader sr = new StreamReader(s, pageEncoding);
                    ret = sr.ReadToEnd();
                    sr.Close();
                    s.Close();
                }
                res.Close();
            }
            catch (Exception ex)
            {
                HttpCode = 404;
                ret = ex.Message;
            }
            finally
            {
            }

            return ret;
        }
        public string HttpPost(string Url, string appkey, string Data, ref int HttpCode)
        {
            string ret = string.Empty;

            try
            {

                ServicePointManager.Expect100Continue = true;
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;   //协议按需选择，不行就都试一遍
                ServicePointManager.ServerCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => { return true; };

                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
                req.Method = "POST";
                req.UserAgent = USERAGENT;
                req.Timeout = 2 * 60 * 1000; //2分钟
                req.Headers.Add(HttpRequestHeader.Authorization, appkey);
                SetRequestHeader(req);

                byte[] btData = Encoding.UTF8.GetBytes(Data);
                req.ContentLength = btData.Length;
                req.ContentType = "application/x-www-form-urlencoded";
                req.CookieContainer = cookie;
                if (proxy.Address != null)
                {
                    req.Proxy = proxy;
                }


                Stream sreq = req.GetRequestStream();
                sreq.Write(btData, 0, btData.Length);
                sreq.Close();

                HttpWebResponse res = (HttpWebResponse)req.GetResponse();
                if (res != null)
                {
                    HttpCode = (int)res.StatusCode;
                    Stream s = res.GetResponseStream();
                    StreamReader sr = new StreamReader(s, pageEncoding);
                    ret = sr.ReadToEnd();
                    sr.Close();
                    s.Close();
                }
                res.Close();
            }
            catch (Exception ex)
            {
                HttpCode = 404;
                ret = ex.Message;
            }
            finally
            {
            }

            return ret;
        }

        /// <summary>
        /// 设置Http头
        /// </summary>
        /// <param name="Req"></param>
        protected void SetRequestHeader(HttpWebRequest Req)
        {
            if (headers != null && headers.Count != 0)
            {
                foreach (var h in headers)
                {
                    Req.Headers.Add(h.Key, h.Value);
                }
            }
        }
        #region 检测百度收录
        /// <summary>
        /// 检测url是否被百度收录
        /// </summary>
        /// <param name="ck_url">检测URL</param>
        /// <returns>-1 百度安全验证 0 未收录 1 已收录</returns>
        public int CheckBaiduInclude(string ck_url)
        {
            int ret = 0;
            var url = $"https://www.baidu.com/s?wd={ck_url}&usm=3&rsv_idx=2&rsv_page=1";

            #region 构造随机ip
            int[][] IpRange = {
                new int[]{607649792,608174079},//36.56.0.0-36.63.255.255
                new int[]{1038614528,1039007743},//61.232.0.0-61.237.255.255
                new int[]{1783627776,1784676351},//106.80.0.0-106.95.255.255
                new int[]{2035023872,2035154943},//121.76.0.0-121.77.255.255
                new int[]{2078801920,2079064063},//123.232.0.0-123.235.255.255
                new int[]{-1950089216,-1948778497},//139.196.0.0-139.215.255.255
                new int[]{-1425539072,-1425014785},//171.8.0.0-171.15.255.255
                new int[]{-1236271104,-1235419137},//182.80.0.0-182.92.255.255
                new int[]{-770113536,-768606209},//210.25.0.0-210.47.255.255
                new int[]{-569376768,-564133889} //222.16.0.0-222.95.255.255
             };
            Random rdint = new Random();
            int index = rdint.Next(10);
            string ip = NumtoIpAddress(IpRange[index][0] + new Random().Next(IpRange[index][1] - IpRange[index][0]));
            #endregion


            #region 支持https
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            //     ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            ServicePointManager.CheckCertificateRevocationList = true;
            ServicePointManager.DefaultConnectionLimit = 100;
            ServicePointManager.Expect100Continue = false;
            #endregion

            #region 模拟http请求header头
            string host = "https://www.baidu.com";
            string domin = "www.baidu.com";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.Timeout = 60 * 1000; //1分钟
            request.Referer = domin;
            request.ContentType = "application/x-www-form-urlencoded";
            request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8";
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3237.0 Safari/537.36";
            request.Host = domin;
            request.Headers.Add("CLIENT-IP", ip);
            request.Headers.Add("X-FORWARDED-FOR", ip);

            CookieContainer cookie = new CookieContainer();
            cookie.Add(new Uri(host), new Cookie("BAIDUID", "DC39ADE1344FD0B5495EC9484098BEC9:FG=1"));
            cookie.Add(new Uri(host), new Cookie("BIDUPSID", "DC39ADE1344FD0B5495EC9484098BEC9"));
            cookie.Add(new Uri(host), new Cookie("PSTM", "1585970693"));
            cookie.Add(new Uri(host), new Cookie("COOKIE_SESSION", "0_0_1_1_0_0_0_0_1_0_0_0_0_0_0_0_0_0_1585986882%7C1%230_0_1585986882%7C1"));
            cookie.Add(new Uri(host), new Cookie("BD_HOME", "1"));
            cookie.Add(new Uri(host), new Cookie("H_PS_PSSID", "31358_1458_31326_21104_31111_31594_31644_31463_31051_30824_26350_31163"));
            cookie.Add(new Uri(host), new Cookie("BD_UPN", "12314753"));
            cookie.Add(new Uri(host), new Cookie("delPer", "0"));
            cookie.Add(new Uri(host), new Cookie("BD_CK_SAM", "1"));
            cookie.Add(new Uri(host), new Cookie("PSINO", "5"));
            cookie.Add(new Uri(host), new Cookie("H_PS_645EC", "0252oRJTl2H3os4Qa0ln2V7iKTxJgNI9yoOmNOborFFPLteoBjYyCgPrqt0"));
            cookie.Add(new Uri(host), new Cookie("BDORZ", "B490B5EBF6F3CD402E515D22BCDA1598"));

            request.CookieContainer = cookie;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
            {
                var html = reader.ReadToEnd();
                //Console.WriteLine(html);

                if (html.Contains("wappass.baidu.com"))
                {
                    ret = -1;
                }
                else if (!html.Contains("没有找到该URL") && !html.Contains("<title>页面不存在_百度搜索</title>") && !html.Contains("提交网址"))
                {
                    ret = 1;
                }
                else
                {
                    ret = 0;
                }
            }
            #endregion

            return ret;
        }
        private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //总是接受     
        }
        /*
         * 将十进制转换成ip地址
        */
        private string NumtoIpAddress(int ip)
        {
            int[] b = new int[4];
            string x = "";
            //位移然后与255 做高低位转换
            b[0] = (int)((ip >> 24) & 0xff);
            b[1] = (int)((ip >> 16) & 0xff);
            b[2] = (int)((ip >> 8) & 0xff);
            b[3] = (int)(ip & 0xff);
            x = (b[0]).ToString() + "." + (b[1]).ToString() + "." + (b[2]).ToString() + "." + (b[3]).ToString();
            return x;
        }
        #endregion

        #region 获取本机所有ip地址
        /// <summary>
        /// 获取本机所有ip地址
        /// </summary>
        /// <param name="netType">"InterNetwork":ipv4地址，"InterNetworkV6":ipv6地址</param>
        /// <returns>ip地址集合</returns>
        public static string GetLocalIpAddress(string netType = "InterNetwork")
        {
            string hostName = System.Net.Dns.GetHostName();                    //获取主机名称
            System.Net.IPAddress[] addresses = System.Net.Dns.GetHostAddresses(hostName); //解析主机IP地址

            List<string> IPList = new List<string>();
            if (netType == string.Empty)
            {
                for (int i = 0; i < addresses.Length; i++)
                {
                    IPList.Add(addresses[i].ToString());
                }
            }
            else
            {
                //AddressFamily.InterNetwork表示此IP为IPv4,
                //AddressFamily.InterNetworkV6表示此地址为IPv6类型
                for (int i = 0; i < addresses.Length; i++)
                {
                    if (addresses[i].AddressFamily.ToString() == netType)
                    {
                        IPList.Add(addresses[i].ToString());
                    }
                }
            }
            IPList = IPList.Where(w => !w.StartsWith("169.254") && !w.StartsWith("127.0.0")).Distinct().ToList();
            if (IPList.Count > 0)
            {
                var ret = "[\"" + (string.Join(",", IPList)) + "\"]";
                //ret = Newtonsoft.Json.JsonConvert.SerializeObject(IPList);
                return ret;
            }
            return string.Empty;
        }
        #endregion
    }
    public class BaiduSiteMapHelper
    {
        /// <summary>
        /// 自动推送百度url
        /// </summary>
        /// <param name="posturl"></param>
        /// <param name="postData"></param>
        /// <returns></returns>
        public static string SiteMapInportPost(string posturl, string postData)
        {
            Stream outstream = null;
            Stream instream = null;
            StreamReader sr = null;
            HttpWebResponse response = null;
            HttpWebRequest request = null;
            Encoding encoding = Encoding.GetEncoding("gb2312");
            byte[] data = encoding.GetBytes(postData);
            try
            {
                // 设置参数
                request = WebRequest.Create(posturl) as HttpWebRequest;
                CookieContainer cookieContainer = new CookieContainer();
                request.UserAgent = "curl/7.12.1";

                request.CookieContainer = cookieContainer;
                request.AllowAutoRedirect = true;
                request.Method = "POST";
                request.Host = "data.zz.baidu.com";
                request.ContentType = "text/plain";
                request.ContentLength = data.Length;
                outstream = request.GetRequestStream();
                outstream.Write(data, 0, data.Length);
                outstream.Close();
                //发送请求并获取相应回应数据
                response = request.GetResponse() as HttpWebResponse;
                //直到request.GetResponse()程序才开始向目标网页发送Post请求
                instream = response.GetResponseStream();
                sr = new StreamReader(instream, encoding);
                //返回结果网页（html）代码
                string content = sr.ReadToEnd();
                string err = string.Empty;
                return content;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                return err;
            }
        }
    }
}
